﻿package com.csd.excelimporter;

import java.io.IOException;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.HibernateException;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.csd.excelreader.ExcelFormatChecker;
import com.csd.excelreader.ExcelReaderDriver;


public abstract class BaseImporter extends HibernateDaoSupport{
	
	//Excel中的值
	protected Object excelVal;
	
	//数据库中的值
	protected Object databaseVal;
	
	/**
	 * 虚方法，从表载入一行的值
	 * @throws IOException 
	 */
	abstract protected void readInBuff () throws IOException;
	
	/**
	 * 虚方法，从数据库找到对应的值
	 */
	abstract protected void findoutFromDatabase ();
	
	/**
	 * 虚方法，清空目标表
	 */
	abstract protected boolean clearTable ();

	//格式检查器
	protected ExcelFormatChecker checker;
	
	//excel文件读取器
	protected ExcelReaderDriver reader;
	
	//输入文件的路径
	protected String inputFile;
	
	//数据库写入器 DAO
	protected HibernateDaoSupport writer;
	
	//数据库会话
	//protected Session session;
	
	public HibernateDaoSupport getWriter() {
		return writer;
	}

	public void setWriter(HibernateDaoSupport writer) {
		this.writer = writer;
	}

	/**
	 * 构造函数
	 */
	public BaseImporter()
	{		
		//session = HibernateSessionFactory.getSession();
		checker = null;
		reader = null;
		inputFile = null;
		writer = null;
	}

	/**
	 * @return the inputFile
	 */
	public String getInputFile() {
		return inputFile;
	}

	/**
	 * @param inputFile the inputFile to set
	 */
	public void setInputFile(String inputFile) {
		this.inputFile = inputFile;
	}
	
	/**
	 * 倒入工作初始化
	 * @throws ExcelImportException
	 */
	public void Initialize () throws ExcelImportException
	{
		if (!this.initChecker()){
			System.out.println(" 抛出导入异常  检查器初始化失败 !");
			throw new ExcelImportException("the checker can not be initialized !");
		}		

		
		if (this.checker == null || this.checker.getRestriction().isEmpty() ) {
			System.out.println(" 抛出导入异常  检查器不可用  !");
			throw new ExcelImportException("the checker is not ready !");
		}


		if (this.inputFile == null) {
			System.out.println(" 抛出导入异常  输入文件不可用 !");
			throw new ExcelImportException("the input file is not set !");
		}


		if (this.writer == null) {
			System.out.println(" 抛出导入异常  写入器DAO没有设置 !");
			throw new ExcelImportException("the DAO is null !");
		}


		// 创建新的读取器实例
		this.reader = new ExcelReaderDriver();

		// 载入输入文件，并在失败时抛出异常
		if ( !this.reader.loadInputFile(this.inputFile) ) {
			System.out.println(" 抛出导入异常  输入文件无法加载!");
			throw new ExcelImportException("the input file is NOT available !");
		}
	}
		
	
	/**
	 * 做导入工作，注意：本函数运行之前应该已经将inputFile设置完成，否则抛出异常
	 * @throws ExcelImportException
	 */
	public void doThoroughlyImport() throws ExcelImportException {		
		
		this.Initialize();		
		
		// 创建一个数据库事务
		Transaction trn = null;
		
		try {			
			trn = this.getSession().beginTransaction();
			
			this.clearTable();
			
			if (!this.reader.loadFirstRow()) {
				System.out.println(" 抛出导入异常  无法加载第一行 !");
				throw new ExcelImportException(
						"can not load the first Row of Excel !");
			}
			
			// 循环检查每一行，并存入数据库
			do
			{
				if ( this.checker.checkRow(this.reader) )
				{				
					try
					{
						this.readInBuff();
					}
					catch(IOException ioe)
					{
						throw new ExcelImportException("File Reading Err!", ioe);
					}
					if ( this.excelVal != null && this.checkDBData())
					{						
						this.save();
					}
					else{
						System.out.println(" 抛出导入异常  Excel数据无效错误， 在第 "+this.reader.getCurrRowNo()+" 行");
						throw new ExcelImportException(
								"Wrong Data in Excel, line: " + this.reader.getCurrRowNo() );
					}
				}
				else
				{
					System.out.println(" 抛出导入异常  Excel格式错误， 在第 "+this.reader.getCurrRowNo()+" 行");
					throw new ExcelImportException(
							"Wrong Format in Excel, line: " + this.reader.getCurrRowNo() );
				}
			}
			while ( this.reader.loadNextRow() );


			// 提交事务
			trn.commit();
		} 
		catch (ExcelImportException eie)
		{
			System.out.println("在 基础导入类  捕获 导入异常  伴随有回滚和关闭会话操作 封装后再次抛出!");
			if (trn != null )
				trn.rollback();
			//HibernateSessionFactory.closeSession();
			
			throw new ExcelImportException("Excel Import ERR !", eie);
		}
		catch (HibernateException he) {
			System.out.println("在 基础导入类  捕获 Hibernate异常  封装后抛出导入异常!");
			throw new ExcelImportException("Hibernate ERR !", he);
		}
	}
	
	
	/**
	 * 做导入工作，注意：本函数运行之前应该已经将inputFile设置完成，否则抛出异常
	 * @throws ExcelImportException
	 */
	public void doRefreshImport() throws ExcelImportException {		
		
		this.Initialize();		
		
		// 创建一个数据库事务
		Transaction trn = null;
		
		try {		
			trn = this.getSession().beginTransaction();
			
			if (!this.reader.loadFirstRow()) {
				System.out.println(" 抛出导入异常  无法加载第一行 !");
				throw new ExcelImportException(
						"can not load the first Row of Excel !");
			}
			
			// 循环检查每一行，并存入数据库
			do
			{
				if ( this.checker.checkRow(this.reader) )
				{		
					try
					{
						this.readInBuff();
					}
					catch(IOException ioe)
					{
						throw new ExcelImportException("File Reading Err!", ioe);
					}	
					if ( this.excelVal != null && this.checkDBData())
					{										
						this.findoutFromDatabase();
						if( this.databaseVal == null )
							this.save();
						else
							this.update();
					}
					else{
						System.out.println(" 抛出导入异常  Excel数据无效错误， 在第 "+this.reader.getCurrRowNo()+" 行");
						throw new ExcelImportException(
								"Wrong Data in Excel, line: " + this.reader.getCurrRowNo() );
					}
				}
				else
				{
					System.out.println(" 抛出导入异常  Excel格式错误， 在第 "+this.reader.getCurrRowNo()+" 行");
					throw new ExcelImportException(
							"Wrong Format in Excel, line: " + this.reader.getCurrRowNo() );
				}
			}
			while ( this.reader.loadNextRow() );


			// 提交事务
			trn.commit();
		} 
		catch (ExcelImportException eie)
		{
			System.out.println("在 基础导入类  捕获 导入异常  伴随有回滚和关闭会话操作 封装后再次抛出!");
			if (trn != null )
				trn.rollback();
			//HibernateSessionFactory.closeSession();
			
			throw new ExcelImportException("Excel Import ERR !", eie);
		}
		catch (HibernateException he) {
			System.out.println("在 基础导入类  捕获 Hibernate异常  封装后抛出导入异常!");
			throw new ExcelImportException("Hibernate ERR !", he);
		}
	}
	
	
	/**
	 * 虚方法，初始化 Checker
	 */
	abstract protected boolean initChecker ();
	
	/**
	 * 虚方法，用来保存一行数据到数据库
	 * @param o
	 * @throws ExcelImportException 
	 */
	abstract protected void save () throws ExcelImportException;
	
	/**
	 * 虚方法，用来更改数据库中的一行数据
	 * @param o
	 * @throws ExcelImportException 
	 */
	abstract protected void update () throws ExcelImportException;
	
	/**
	 * 检查数据的正确性，和checker不同，这里检查的不是数据格式，而是数据本身
	 * @return
	 */
	abstract protected boolean checkDBData ();
}
